﻿using CommunityToolkit.Mvvm.Input;
using Mapster;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UpperComputer.Application;
using UpperComputer.WPF.Entry.Common;
using UpperComputer.WPF.Entry.Models;
using YFurion.Application;

namespace UpperComputer.WPF.Entry.ViewModels
{
    public class RolePermissionsViewModel : OperationViewModel
    {
        private readonly IBaseRoleService _roleService;
        private readonly IBaseRolePermissionService _rolePermissionService;
        private readonly IBaseMenuService _menuService;

        /// <summary>
        /// 角色对象
        /// </summary>
        private BaseRoleResultDto _role;

        /// <summary>
        /// 是否完成选中或不选中
        /// </summary>
        private bool _isFinished = true;

        /// <summary>
        /// 菜单选中命令
        /// </summary>
        public RelayCommand<CheckedMenuModel> MenuCheckCommand { get; }

        /// <summary>
        /// 选中树形菜单集合
        /// </summary>
        public ObservableCollection<CheckedMenuModel> Menus { get; } = new ObservableCollection<CheckedMenuModel>();

        public RolePermissionsViewModel(IBaseRoleService roleService, IBaseRolePermissionService rolePermissionService, IBaseMenuService menuService,long id)
        {
            _roleService = roleService;
            _rolePermissionService = rolePermissionService;
            _menuService = menuService;
            Id = id;
            MenuCheckCommand = new RelayCommand<CheckedMenuModel>(MenuCheckCommand_Execute);
        }

        #region 加载
        protected override async Task LoadAsync(object parameter, CancellationToken cancellationToken)
        {
            _role = await _roleService.GetCacheById(Id, cancellationToken);
            List<BaseMenuResultDto> originMenus = await _menuService.GetMenus(new BaseMenuResultRequestDto
            {
                IsActive = true,
                ShowMenuButtons = true,
                CanSearchMenuButtons = true,
            }, cancellationToken);
            PagedResultDto<BaseRolePermissionDto> brpDto = await _rolePermissionService.GetAll(new BaseRolePermissionResultRequestDto
            {
                RoleCodes = new string[] { _role.Code }
            }, cancellationToken);
            AddCheckedMenu(Menus, originMenus, brpDto.Items, null);
        }
        #endregion

        #region 选中或不选中
        private void AddCheckedMenu(ObservableCollection<CheckedMenuModel> checkedMenus, ICollection<BaseMenuResultDto> originMenus, IReadOnlyList<BaseRolePermissionDto> rolePermissions, CheckedMenuModel checkedParentMenu)
        {
            foreach (BaseMenuResultDto item in originMenus)
            {
                CheckedMenuModel checkedMenu = item.Adapt<CheckedMenuModel>();
                checkedMenu.CheckedParent = checkedParentMenu;
                checkedMenu.IsChecked = rolePermissions.Any(rp => rp.PermissionCode.Equals(item.Type == 1 ? item.Code : $"{item.ParentCode}{item.Code}"));
                checkedMenus.Add(checkedMenu);
                if (item.Childrens?.Count > 0)
                {
                    AddCheckedMenu(checkedMenu.CheckedChildrens, item.Childrens, rolePermissions, checkedMenu);
                }
            }
        }

        private void MenuCheckCommand_Execute(CheckedMenuModel checkedMenu)
        {
            if (!_isFinished)
            {
                return;
            }
            _isFinished = false;
            CheckOrUnCheckParentMenu(checkedMenu);
            CheckOrUnCheckChildrenMenus(checkedMenu);
            _isFinished = true;
        }

        private void CheckOrUnCheckParentMenu(CheckedMenuModel checkedMenu)
        {
            if (checkedMenu.CheckedParent != null)
            {
                checkedMenu.CheckedParent.IsChecked = checkedMenu.IsChecked ? true : checkedMenu.CheckedParent.CheckedChildrens.Any(cm => cm.IsChecked && !cm.Equals(checkedMenu));
                CheckOrUnCheckParentMenu(checkedMenu.CheckedParent);
            }
        }

        private void CheckOrUnCheckChildrenMenus(CheckedMenuModel checkedMenu)
        {
            foreach (CheckedMenuModel item in checkedMenu.CheckedChildrens)
            {
                item.IsChecked = checkedMenu.IsChecked;
                CheckOrUnCheckChildrenMenus(item);
            }
        }
        #endregion

        #region 确定
        protected override async Task OkAsync(object parameter, CancellationToken cancellationToken)
        {
            await TryExecuteCommandAysnc(async cancellationToken =>
            {
                List<BaseMenuResultDto> permissionMenus = new List<BaseMenuResultDto>();
                AddPermissionMenu(permissionMenus, Menus);
                await _rolePermissionService.PermissionAsync(_role.Code, permissionMenus, cancellationToken);
                CloseRootDialog(true);
            }, cancellationToken);
        }

        private void AddPermissionMenu(List<BaseMenuResultDto> menus, ObservableCollection<CheckedMenuModel> checkedMenus)
        {
            foreach (CheckedMenuModel item in checkedMenus)
            {
                if (item.IsChecked)
                {
                    menus.Add(item);
                    AddPermissionMenu(menus, item.CheckedChildrens);
                }
            }
        }
        #endregion
    }
}
